package com.kongchengji.zhanguafou.service;

import com.alibaba.fastjson.JSONObject;
import com.kongchengji.zhanguafou.constant.WxInfo;
import com.kongchengji.zhanguafou.dao.ICPDAO;
import com.kongchengji.zhanguafou.dao.QuartzDAO;
import com.kongchengji.zhanguafou.domain.ICPDO;
import com.kongchengji.zhanguafou.domain.QuartzDO;
import com.kongchengji.zhanguafou.domain.Result;
import com.kongchengji.zhanguafou.utils.BuildCustomerMsgUtil;
import com.kongchengji.zhanguafou.utils.FormatTimeUtil;
import okhttp3.*;
import org.openqa.selenium.*;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.imageio.ImageIO;
import javax.rmi.CORBA.Tie;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

@Service
public class ICPService {
    @Autowired
    JobService jobService;
    @Autowired
    private QuartzDAO quartzDAO;
    @Autowired
    private ICPDAO icpDao;
    private String cookie;
    private String code;
    @Value("${pic.location}")
    private String picLocation;
    @Value("${chrome.driver.location}")
    private String chromeDriverLocation;
    @Autowired
    private OCRService ocrService;
    Logger logger = LoggerFactory.getLogger(ICPService.class);

    /**
     * 通过谷歌的无头浏览器获得cookie,查询备案信息,返回结果
     *
     * @param siteDomain 查询对象
     * @return 如果为查询到信息, 返回false
     */
    public String getICPResponse(String siteDomain) throws IOException {
        WebDriver driver = null;
        boolean result = false;
        try {
            driver = getChromeDriver();
            driver.get("http://www.miitbeian.gov.cn/");
            Thread.sleep(3000);
        } catch (IOException e) {
            logger.error("驱动位置异常");
            e.printStackTrace();
        } catch (InterruptedException e) {
            logger.error("中断异常");
            e.printStackTrace();
        }
        StringBuilder strCookie = new StringBuilder();
        Set<Cookie> cookies = driver.manage().getCookies();
        for (Cookie cookie : cookies) {
            strCookie.append(";").append(cookie.getName()).append("=").append(cookie.getValue());
        }
        strCookie.deleteCharAt(0);
        //获得cookie
        cookie = strCookie.toString();
        //下载验证码图片
        while (!result) {
            Random random = new Random();
            int randomNum = random.nextInt(100);
            Request request = new Request.Builder()
                    .addHeader("Cookie", cookie)
                    .addHeader("Refer", "http://www.miitbeian.gov.cn/icp/publish/query/icpMemoInfo_showPage.action")
                    .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36")
                    .addHeader("Accept","image/webp,image/apng,image/*,*/*;q=0.8")
                    .addHeader("Accept-Encoding","gzip, deflate")
                    .addHeader("Accept-Language","zh-CN,zh;q=0.9")
                    .addHeader("Cache-Control","no-cache")
                    .addHeader("Connection","keep-alive")
                    .addHeader("Host","www.miitbeian.gov.cn")
                    .addHeader("Pragma","no-cache")
                    .url("http://www.miitbeian.gov.cn/getVerifyCode?" + randomNum)
                    .build();
            OkHttpClient client = new OkHttpClient();
            try {
                FileOutputStream outputStream = new FileOutputStream(picLocation + "code.jpg");
                Response response = client.newCall(request).execute();
                outputStream.write(response.body().bytes());
                //休眠2秒，防止程序无法读取刚写入的图片
                Thread.sleep(2000);
                //对图片进行二值化并去除部分干扰线
                cleanLinesInImage(new File(picLocation  + "code.jpg"), picLocation + "image");
                //休眠2秒，防止程序无法读取刚写入的图片
                Thread.sleep(2000);
                //二次去除干扰线同时得到验证码的值并验证
                BufferedImage image = removeLine(ImageIO.read(new FileInputStream(picLocation + "image/" + "code.jpg")), 2);
                ImageIO.write(image, "jpg", new FileOutputStream(picLocation + "image/code1.jpg"));
                //休眠2秒，防止程序无法读取刚写入的图片
                Thread.sleep(2000);
            } catch (FileNotFoundException e) {
                logger.error("验证码图片位置出错,请修改配置文件");
                e.printStackTrace();
            }
//因为获取验证码可能多次出现网络异常或其它异常，应该抛出去
//            catch (IOException e) {
//                logger.error("请求验证码抛出io异常");
//                e.printStackTrace();
//            }
            catch (InterruptedException e) {
                logger.error("中断异常");
                e.printStackTrace();
            } finally {
                driver.quit();
            }
            code = ocrService.recognizePic();
            System.err.println("code:" + code);
            result = checkCode(code);
        }


        //通过验证码查询结果
        RequestBody requestBody = new FormBody.Builder()
                .add("condition", "1")
                .add("siteName","")
                .add("siteUrl","")
                .add("mainLicense","")
                .add("siteIp","")
                .add("unitName","")
                .add("mainUnitCertNo","")
                .add("siteDomain", siteDomain)
                .add("verifyCode", code)
                .add("certType", "-1")
                .add("mainUnitNature", "-1")
                .build();
        Request request = new Request.Builder()
                .addHeader("Cookie", cookie)
                .addHeader("Refer", "http://www.miitbeian.gov.cn/icp/publish/query/icpMemoInfo_showPage.action")
                .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36")
                .addHeader("Accept","application/json, text/javascript, */*")
                .addHeader("Accept-Language","zh-CN,zh;q=0.9")
                .addHeader("Cache-Control","no-cache")
                .addHeader("Connection","keep-alive")
                .addHeader("Origin","http://www.miitbeian.gov.cn")
                .addHeader("Host","www.miitbeian.gov.cn")
                .addHeader("Pragma","no-cache")
                .addHeader("Content-Type","application/x-www-form-urlencoded")
                .addHeader("X-Requested-With","XMLHttpRequest")
                .post(requestBody)
                .url("http://www.miitbeian.gov.cn/icp/publish/query/icpMemoInfo_searchExecute.action")
                .build();
        OkHttpClient client = new OkHttpClient();
        try {
            Response response = client.newCall(request).execute();
            String body = response.body().string();
            return body;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询该用户监控的域名备案信息，并根据openId发送给指定用户
     *
     * @param map
     * @return
     */
    public String selectByOpenId(Map<String, String> map) {
        String toUserName = map.get("ToUserName");
        String openId = map.get("FromUserName");
        String defaultMessage;
        Example example = new Example(QuartzDO.class);
        example.createCriteria().andEqualTo("openId", openId).andEqualTo("jobGroup", "Icp");
        List<QuartzDO> quartzDOS = quartzDAO.selectByExample(example);
        if(quartzDOS.size() == 0){
            defaultMessage = "你还未添加监控";
        }else {
            defaultMessage = "客官别急,正在查询,请稍等";
            //耗时操作,如果5秒内微信服务器得不到响应会重试,并在公众号中出现提供的服务出现故障的提示,所以异步执行。
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (QuartzDO quartzDO : quartzDOS) {
                        StringBuilder stringBuilder = new StringBuilder();
                        String response = null;
                        boolean flag = true;
                        while (flag) {
                            try {
                                response = getICPResponse(quartzDO.getUrl());
                                //正常执行，未抛异常,则跳出循环
                                flag = false;
                            } catch (IOException e) {
                                //可能是由于多次请求验证码出错
                                e.printStackTrace();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        //先要判断下是否含有记录
                        if (response.contains("没有符合条件的记录")) {
                            stringBuilder.append(quartzDO.getUrl()).append(":可能备案掉了");
                        } else {
                            //处理返回的数据并提取有用的数据
                            Map<String, String> recordMap = filterResponse(response);
                            stringBuilder.append(
                                    "主办单位名称:" + recordMap.get("name") + "\n" +
                                            "主办单位性质:" + recordMap.get("UnitNature") + "\n" +
                                            "网站备案/许可证号:" + recordMap.get("license") + "\n" +
                                            "网站名称:" + recordMap.get("station") + "\n" + "审核时间:" + recordMap.get("time") + "\n" +
                                            "是否限制接入:" + recordMap.get("access") + "\n");
                        }
                        String contentJson = BuildCustomerMsgUtil.buildMessage(stringBuilder.toString(), openId);
                        RequestBody requestBody =
                                FormBody.create(MediaType.parse("application/json;charset=utf-8"), contentJson);
                        Request request = new Request
                                .Builder()
                                .url("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + WxInfo.accessToken.getToken())
                                .post(requestBody)
                                .build();
                        OkHttpClient okHttpClient = new OkHttpClient();
                        try {
                            okHttpClient.newCall(request).execute();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

            });
            t.start();
        }
        String result = String
                .format(
                        "<xml>" +
                                "<ToUserName><![CDATA[%s]]></ToUserName>" +
                                "<FromUserName><![CDATA[%s]]></FromUserName>" +
                                "<CreateTime>%s</CreateTime>" +
                                "<MsgType><![CDATA[text]]></MsgType>" +
                                "<Content><![CDATA[%s]]></Content>" +
                                "</xml>",
                        openId, toUserName, FormatTimeUtil.getFormatTime(),
                        defaultMessage);
        return result;
    }


    /**
     * 提取出查询信息中的有用信息
     *
     * @param response 查询备案返回结果
     * @return 返回封装成map集合的信息
     */
    public Map<String, String> filterResponse(String response) {
        //匹配<tr id="1"></tr>
        Matcher matcher = Pattern.compile("<tr.*?[id=\"1\"].*?>(.*?(\\s)*)*?</tr>").matcher(response);
        if (matcher.find()) {
            String keyMessage = matcher.group();
            //拿到<td>标签里的文本
            matcher = Pattern.compile("<td.*?>(.*?(\\s)*)*?(?=</td>)").matcher(keyMessage);
            Map<String, String> map = new HashMap<>();
            int index = 0;
            while (matcher.find()) {
                index++;
                //主办单位名称
                if (index == 2) {
                    map.put("name", manageGroug(matcher.group()));
                }
                //主办单位性质
                if (index == 3) {
                    map.put("UnitNature", manageGroug(matcher.group()));
                }
                //网站备案/许可证号
                if (index == 4) {
                    map.put("license", manageGroug(matcher.group()));
                }
                //网站名称
                if (index == 5) {
                    map.put("station", manageGroug(matcher.group()));
                }
                //审核时间
                if (index == 7) {
                    String time = manageGroug(matcher.group());
                    if(time.contains("&nbsp")){
                        int last = time.indexOf("&");
                        time = time.substring(0,last);
                    }
                    map.put("time", time);
                }
                //是否限制接入
                if (index == 8) {
                    map.put("access", manageGroug(matcher.group()));
                }
            }
            return map;
        }
        return null;
    }

    /**
     * 处理正则匹配的内容
     *
     * @param group 匹配到的内容
     * @return 返回处理后的内容内容
     */
    private String manageGroug(String group) {
        if (group.contains("&nbsp;")) {
            group = group.replaceAll("&nbsp;", "");
        }
        return group.substring(group.indexOf(">") + 1);
    }

    /**
     * 如果没有查询到备案信息,返回false
     *
     * @param siteDomain 域名
     * @return 返回结果
     */
    public boolean icpResult(String siteDomain) {
        String response = null;
        boolean flag = true;
        while (flag) {
            try {
                response = getICPResponse(siteDomain);
                //正常执行，未抛异常,则跳出循环
                flag = false;
            } catch (IOException e) {
                //可能是由于多次请求验证码出错
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (response != null) {
            //因为没有备案信息时返回结果中包含"没有符合条件的记录"
            return !response.contains("没有符合条件的记录");
        }
        return true;
    }


    /**
     * 保存icp配置
     *
     * @param icpdo
     * @return 返回保存结果
     */
    public Result saveConfig(ICPDO icpdo) {
        QuartzDO quartzDO = buildQuartz(icpdo, "com.kongchengji.zhanguafou.quartz.ICPScheduleTask");
        //通过jobName判断任务是否存在数据库,不在将任务保存数据库
        Example example = new Example(QuartzDO.class);
        example.createCriteria().andEqualTo("jobName", quartzDO.getJobName());
        int count = quartzDAO.selectCountByExample(example);
        if (count != 0) {
            return Result.error("该域名已添加,如果未启动监控,请在监控列表中启动");
        }
        //将icp对象保存数据库
        icpDao.insertSelective(icpdo);
        //将任务信息保存于数据库
        quartzDAO.insertSelective(quartzDO);
        jobService.save(quartzDO);
        return Result.ok("添加监控成功");
    }

    /**
     * 根据时间表达式构造quartz对象
     * @param icpdo icp对象
     * @param clazz 实际执行的任务类
     * @return
     */
    private QuartzDO buildQuartz(ICPDO icpdo, String clazz) {
        //根据用户所选的时间组成cron表达式
        Random random = new Random();
        int minutes = random.nextInt(60);
        int hours = random.nextInt(24);
        String cron = "0 "+minutes+" "+ hours + " 1/1" + " * ?";
        QuartzDO quartz = new QuartzDO();
        //组成任务的唯一标识
        quartz.setJobName("Icp" + icpdo.getSiteDomain() + icpdo.getOpenId());
        quartz.setJobGroup("Icp");
        quartz.setDescription("监控域名备案是否还在");
        quartz.setJobClassName(clazz);
        quartz.setOpenId(icpdo.getOpenId());
        quartz.setUrl(icpdo.getSiteDomain());
        quartz.setCronExpression(cron);
        return quartz;
    }


    /**
     * 对字符串进行url编码
     *
     * @param str 字符串
     * @return 返回url编码
     */
    private String getURLEncoderString(String str) {
        String result = null;
        try {
            result = URLEncoder.encode(URLEncoder.encode(str, "utf-8"), "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 校验验证码
     *
     * @param code 验证码
     * @return 返回结果
     */
    private boolean checkCode(String code) {
        String urlCode = getURLEncoderString(code);
        RequestBody body = new FormBody.Builder()
                .add("validateValue", urlCode)
                .build();

        Request request = new Request.Builder()
                .addHeader("Cookie", cookie)
                .addHeader("Refer", "http://www.miitbeian.gov.cn/icp/publish/query/icpMemoInfo_showPage.action")
                .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36")
                .addHeader("Accept","application/json, text/javascript, */*")
                .addHeader("Accept-Encoding","gzip, deflate")
                .addHeader("Accept-Language","zh-CN,zh;q=0.9")
                .addHeader("Cache-Control","no-cache")
                .addHeader("Origin","http://www.miitbeian.gov.cn")
                .addHeader("Host","www.miitbeian.gov.cn")
                .addHeader("Pragma","no-cache")
                .addHeader("Content-Type","application/x-www-form-urlencoded")
                .addHeader("X-Requested-With","XMLHttpRequest")
                .post(body)
                .url("http://www.miitbeian.gov.cn/common/validate/validCode.action")
                .build();
        OkHttpClient client = new OkHttpClient();
        try {
            Response response = client.newCall(request).execute();
            JSONObject jsonObject = JSONObject.parseObject(response.body().string());
            return jsonObject.getBoolean("result");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 根据干扰线的粗细去除干扰线
     *
     * @param img 图片
     * @param px  干扰线的粗细
     * @return 返回图片
     */
    private BufferedImage removeLine(BufferedImage img, int px) {
        if (img != null) {
            int width = img.getWidth();
            int height = img.getHeight();
            for (int x = 0; x < width; x++) {
                List<Integer> list = new ArrayList<>();
                for (int y = 0; y < height; y++) {
                    int count = 0;
                    while (y < height - 1 && isBlack(img.getRGB(x, y))) {
                        count++;
                        y++;
                    }
                    if (count <= px && count > 0) {
                        for (int i = 0; i <= count; i++) {
                            list.add(y - i);
                        }
                    }
                }
                if (list.size() != 0) {
                    for (int i : list) {
                        img.setRGB(x, i, Color.white.getRGB());
                    }
                }
            }
        }
        return img;
    }


    /**
     * 获得chromedriver实例
     *
     * @return 返回ChromeDriver
     * @throws IOException chromedriver存储位置错误
     */
    private WebDriver getChromeDriver() throws IOException {
        // 创建一个 ChromeDriver 的接口，用于连接 Chrome（chromedriver.exe 的路径可以任意放置，只要在newFile（）的时候写入你放的路径即可）
        ChromeDriverService service = new ChromeDriverService.Builder().usingDriverExecutable(new File(chromeDriverLocation)).usingAnyFreePort().build();
//        PhantomJSDriverService service1 = new PhantomJSDriverService.Builder().usingPhantomJSExecutable(new File("F:\\phantomjs-2.1.1-windows\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe")).usingAnyFreePort().build();
//        System.setProperty("webdriver.chrome.driver",chromeDriverLocation);
//        System.setProperty(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,"F:\\phantomjs-2.1.1-windows\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe");
        service.start();
        // 创建一个 Chrome 的浏览器实例
        ChromeOptions chromeOptions = new ChromeOptions();
        chromeOptions.addArguments(
                "user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36","disable-infobars","--no-sandbox",
                "Accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
                "Accept-Encoding=gzip,deflate","Accept-Language=zh-CN,zh;q=0.9","Connection=keep-alive",
                "Host=www.miitbeian.gov.cn","Upgrade-Insecure-Requests=1","--headless");
//      DesiredCapabilities dcaps = new DesiredCapabilities();
//      dcaps.setCapability("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");
        return new ChromeDriver(service, chromeOptions);
    }


    /**
     * 将图片二值化并去除部分干扰线
     *
     * @param sfile   需要去噪的图像
     * @param destDir 去噪后的图像保存地址
     * @throws IOException 图片位置错误抛出io异常
     */
    private void cleanLinesInImage(File sfile, String destDir) throws IOException {
        File destF = new File(destDir);
        if (!destF.exists()) {
            destF.mkdirs();
        }

        BufferedImage bufferedImage = ImageIO.read(sfile);
        int h = bufferedImage.getHeight();
        int w = bufferedImage.getWidth();

        // 灰度化
        int[][] gray = new int[w][h];
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                int argb = bufferedImage.getRGB(x, y);
                // 图像加亮（调整亮度识别率非常高）
                int r = (int) (((argb >> 16) & 0xFF) * 1.1 + 30);
                int g = (int) (((argb >> 8) & 0xFF) * 1.1 + 30);
                int b = (int) (((argb) & 0xFF) * 1.1 + 30);
                if (r >= 255) {
                    r = 255;
                }
                if (g >= 255) {
                    g = 255;
                }
                if (b >= 255) {
                    b = 255;
                }
                gray[x][y] = (int) Math
                        .pow((Math.pow(r, 2.2) * 0.2973 + Math.pow(g, 2.2)
                                * 0.6274 + Math.pow(b, 2.2) * 0.0753), 1 / 2.2);
            }
        }

        // 二值化
        int threshold = ostu(gray, w, h);
        BufferedImage binaryBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                if (gray[x][y] > threshold) {
                    gray[x][y] |= 0x00FFFF;
                } else {
                    gray[x][y] &= 0xFF0000;
                }
                binaryBufferedImage.setRGB(x, y, gray[x][y]);
            }
        }

        //去除干扰线条
        for (int y = 1; y < h - 1; y++) {
            for (int x = 1; x < w - 1; x++) {
                boolean flag = false;
                if (isBlack(binaryBufferedImage.getRGB(x, y))) {
                    //左右均为空时，去掉此点
                    if (isWhite(binaryBufferedImage.getRGB(x - 1, y)) && isWhite(binaryBufferedImage.getRGB(x + 1, y))) {
                        flag = true;
                    }
                    //上下均为空时，去掉此点
                    if (isWhite(binaryBufferedImage.getRGB(x, y + 1)) && isWhite(binaryBufferedImage.getRGB(x, y - 1))) {
                        flag = true;
                    }
                    //斜上下为空时，去掉此点
                    if (isWhite(binaryBufferedImage.getRGB(x - 1, y + 1)) && isWhite(binaryBufferedImage.getRGB(x + 1, y - 1))) {
                        flag = true;
                    }
                    if (isWhite(binaryBufferedImage.getRGB(x + 1, y + 1)) && isWhite(binaryBufferedImage.getRGB(x - 1, y - 1))) {
                        flag = true;
                    }
                    if (flag) {
                        binaryBufferedImage.setRGB(x, y, -1);
                    }
                }
            }
        }

        ImageIO.write(binaryBufferedImage, "jpg", new File(destDir, sfile
                .getName()));
    }

    private boolean isBlack(int colorInt) {
        Color color = new Color(colorInt);
        return (color.getRed() + color.getGreen() + color.getBlue() <= 300);
    }

    private boolean isWhite(int colorInt) {
        Color color = new Color(colorInt);
        return color.getRed() + color.getGreen() + color.getBlue() > 300;

    }


    private int getColorBright(int colorInt) {
        Color color = new Color(colorInt);
        return color.getRed() + color.getGreen() + color.getBlue();
    }

    private int ostu(int[][] gray, int w, int h) {
        int[] histData = new int[w * h];
        // Calculate histogram
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                int red = 0xFF & gray[x][y];
                histData[red]++;
            }
        }

        // Total number of pixels
        int total = w * h;

        float sum = 0;
        for (int t = 0; t < 256; t++)
            sum += t * histData[t];

        float sumB = 0;
        int wB = 0;
        int wF;

        float varMax = 0;
        int threshold = 0;

        for (int t = 0; t < 256; t++) {
            wB += histData[t]; // Weight Background
            if (wB == 0)
                continue;

            wF = total - wB; // Weight Foreground
            if (wF == 0)
                break;

            sumB += (float) (t * histData[t]);

            float mB = sumB / wB; // Mean Background
            float mF = (sum - sumB) / wF; // Mean Foreground

            // Calculate Between Class Variance
            float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);

            // Check if new maximum found
            if (varBetween > varMax) {
                varMax = varBetween;
                threshold = t;
            }
        }

        return threshold;
    }
}
